package main

import (
	"fmt"
	"math/rand"
	"time"

	sentinel "github.com/alibaba/sentinel-golang/api"
	"github.com/alibaba/sentinel-golang/core/base"
	"github.com/alibaba/sentinel-golang/core/config"
	"github.com/alibaba/sentinel-golang/core/flow"
	"github.com/alibaba/sentinel-golang/logging"
)

var cfg = &config.Entity{
	Version: "v1",
	Sentinel: config.SentinelConfig{
		App: struct {
			Name string
			Type int32
		}{
			Name: "fps-mars",
			Type: config.DefaultAppType,
		},
		Log: config.LogConfig{
			Logger: NewSentinelLoggerAdapter(),
			Dir:    "",
			UsePid: false,
			Metric: config.MetricLogConfig{
				SingleFileMaxSize: config.DefaultMetricLogSingleFileMaxSize,
				MaxFileCount:      config.DefaultMetricLogMaxFileAmount,
				FlushIntervalSec:  0,
			},
		},
		Stat: config.StatConfig{
			GlobalStatisticSampleCountTotal: base.DefaultSampleCountTotal,
			GlobalStatisticIntervalMsTotal:  base.DefaultIntervalMsTotal,
			MetricStatisticSampleCount:      base.DefaultSampleCount,
			MetricStatisticIntervalMs:       base.DefaultIntervalMs,
			System: config.SystemStatConfig{
				CollectIntervalMs:       0,
				CollectLoadIntervalMs:   0,
				CollectCpuIntervalMs:    0,
				CollectMemoryIntervalMs: 0,
			},
		},
		UseCacheTime: false,
	}}

func main() {
	err := sentinel.InitWithConfig(cfg)
	if err != nil {
		panic(err)
	}

	_, err = flow.LoadRules([]*flow.Rule{
		{
			Resource:               "some-test",
			Threshold:              10,
			TokenCalculateStrategy: flow.Direct,
			ControlBehavior:        flow.Reject,
		},
	})
	if err != nil {
		panic(err)
	}

	ch := make(chan struct{})
	for i := 0; i < 10; i++ {
		go func() {
			for {
				se, err := sentinel.Entry("some-test")
				if err != nil {
					// Nothing to do...
				} else {
					// fmt.Println("passed....")
					time.Sleep(time.Duration(rand.Uint64()%10) * time.Millisecond)
					se.Exit()
				}
			}
		}()
	}
	<-ch
}

type SentinelLoggerAdapter struct {
}

func NewSentinelLoggerAdapter() *SentinelLoggerAdapter {
	return &SentinelLoggerAdapter{}
}

func (sla *SentinelLoggerAdapter) Logger() logging.Logger {
	return sla
}

func (sla *SentinelLoggerAdapter) Debug(msg string, keysAndValues ...interface{}) {
	fmt.Println(msg, keysAndValues)
}

func (sla *SentinelLoggerAdapter) Info(msg string, keysAndValues ...interface{}) {
	fmt.Println(msg, keysAndValues)
}

func (sla *SentinelLoggerAdapter) Warn(msg string, keysAndValues ...interface{}) {
	fmt.Println(msg, keysAndValues)
}

func (sla *SentinelLoggerAdapter) Error(err error, msg string, keysAndValues ...interface{}) {
	fmt.Println(msg, keysAndValues)
}

func (sla *SentinelLoggerAdapter) DebugEnabled() bool {
	return true
}

func (sla *SentinelLoggerAdapter) InfoEnabled() bool {
	return true
}
func (sla *SentinelLoggerAdapter) WarnEnabled() bool {
	return true
}

func (sla *SentinelLoggerAdapter) ErrorEnabled() bool {
	return true
}
